package com.gk.panda.apis.patrol.servicr.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gk.panda.apis.Vo.UserOrgVo;
import com.gk.panda.apis.excelobject.ExPatrolDTO;
import com.gk.panda.apis.patrol.commons.*;
import com.gk.panda.apis.patrol.mapper.LocationInfoMapper;
import com.gk.panda.apis.patrol.mapper.PatrolMapper;
import com.gk.panda.apis.patrol.servicr.*;
import com.gk.panda.apis.service.OrgService;
import com.gk.panda.apis.service.UserService;
import com.gk.panda.commons.exception.ServerException;
import com.gk.panda.commons.result.Result;
import com.gk.panda.commons.util.UserUtil;
import com.gk.panda.pojo.Org;
import com.gk.panda.pojo.User;
import com.gk.panda.pojo.patrol.dto.*;
import com.gk.panda.pojo.patrol.entity.LocationInfoEntity;
import com.gk.panda.pojo.patrol.entity.PatrolEntity;
import com.gk.panda.pojo.patrol.entity.ReportEntity;
import com.gk.panda.pojo.patrol.entity.ReportResourceEntity;
import com.gk.panda.pojo.patrol.request.*;
import com.gk.panda.pojo.patrol.request.PatrolQueryPageRequest;
import com.gk.panda.pojo.patrol.request.SavePatrolRequest;
import com.gk.panda.pojo.patrol.request.StopPatrolRequest;
import com.gk.panda.pojo.patrol.request.UpdatePatrolRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：xxz
 * @Create: 2022/11/1 15:48
 */
@Service
@Slf4j
public class PatrolServiceImpl extends ServiceImpl<PatrolMapper, PatrolEntity> implements PatrolService {


    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private ReportService reportService;
    @Autowired
    private DateUtils dateUtils;

    @Autowired
    private ReportResourceService resourceService;

    @Autowired
    private UserService userService;

    @Autowired
    private OrgService orgService;

    @Autowired
    private LocationInfoMapper locationInfoMapper;

    @Autowired
    private LocationInfoService locationInfoService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private AsyncPatrolService asyncPatrolService;

    @Autowired
    private ReportResourceService reportResourceService;


//    public static final String name = "wym";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> create(SavePatrolRequest request) {
        String username = UserUtil.getCurrentUser();
        // 检测是否重复提交
        if (submit("patrol:save:submit:" + username)) {
            return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "操作频繁请稍后再试");
        }
        int orgId = UserUtil.getCurrentUserOrgId();
        String abbr = UserUtil.getCurrentUserOrgAbbr();
        // 检测当前用户是否还有未结束的巡护
        if (!StringUtils.isEmpty(this.getPatrolByName(username))) {
            return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "当前用户还有未结束的巡护不可创建新的巡护");
        }

//            Integer totalPrgId = 1;
//            Integer branchOrgId = 1;

//            String patrolNames;
//            String othersPatrolNames = null;
//            String unit = null;
//            // 拼接巡护人员信息
//            if (!CollectionUtils.isEmpty(request.getPatrolNames())) {
//                patrolNames = request.getPatrolNames().stream().collect(Collectors.joining("、"));
//                // 不包含自己就将自己添加进去
//                if (!patrolNames.contains(name)) {
//                    patrolNames += "," + name;
//                }
//            } else {
//                //巡护人员为空使用创建人填充
//                patrolNames = name;
//            }
//            // 拼接其他人员信息
//            if (!CollectionUtils.isEmpty(request.getOthersPatrolNames())) {
//                othersPatrolNames = request.getOthersPatrolNames().stream().collect(Collectors.joining("、"));
//            }
//            // 拼接单位信息
//            if (!CollectionUtils.isEmpty(request.getUnits())) {
//                unit = request.getUnits().stream().collect(Collectors.joining("、"));
//            }

        PatrolEntity patrolEntity = new PatrolEntity();
        // 巡护类型为样线巡护时路线信息不能为空
        if (StateEnum.PATROL_TYPE.TRANSECT.getType().equals(request.getType())) {
            if (StringUtils.isEmpty(request.getTransectSn())) {
                return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "请选择样线!");
            }
            patrolEntity.setLine(request.getTransectSn());
        }
        Date date = new Date();
        patrolEntity.setTotalOrgId(orgId);
//            patrolEntity.setBranchOrgId(branchOrgId);
        patrolEntity.setPatrolNum(this.createOrderNum(abbr, "yyyyMMdd"));
        patrolEntity.setType(request.getType());
        //其他人员 、巡护人员都为空报错
        if (StringUtils.isEmpty(request.getPatrolNames()) && StringUtils.isEmpty(request.getOthersPatrolNames())) {
            return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "填写巡护人员错误!");
        }
        if (!StringUtils.isEmpty(request.getPatrolNames())) {
            patrolEntity.setPeople(request.getPatrolNames());
        }

        if (!StringUtils.isEmpty(request.getOthersPatrolNames())) {
            patrolEntity.setOthersPeople(request.getOthersPatrolNames());
        }

        patrolEntity.setStartTime(date);
        patrolEntity.setCreateTime(date);
        patrolEntity.setCreateBy(username);
        patrolEntity.setModifyBy(username);
        patrolEntity.setModifyTime(date);
        patrolEntity.setStartLon(request.getLon());
        patrolEntity.setStartLat(request.getLat());

        if (!StringUtils.isEmpty(request.getName())) {
            patrolEntity.setName(request.getName());
        }
        if (!StringUtils.isEmpty(request.getTheme())) {
            patrolEntity.setTheme(request.getTheme());
        }
        if (!StringUtils.isEmpty(request.getUnits())) {
            patrolEntity.setUnit(request.getUnits());
        }

        patrolEntity.setState(StateEnum.PATROL_STATE.UNDERWAY.getState());

        // 巡护路程默认为0
        patrolEntity.setRoute("0");


        boolean flag = this.save(patrolEntity);

        //添加开始经纬度到位置信息表

        LocationInfoEntity locationInfoEntity = new LocationInfoEntity();
        locationInfoEntity.setCreateTime(new Date());
        locationInfoEntity.setLon(request.getLon());
        locationInfoEntity.setLat(request.getLat());
        locationInfoEntity.setIsEvent(0);
        locationInfoEntity.setPatrolId(patrolEntity.getId());
        locationInfoService.save(locationInfoEntity);

        if (flag) {
            return Result.ok(patrolEntity.getId());
        }
        return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "操作失败请稍后再试");

    }

    @Override
    public Result<?> stop(StopPatrolRequest request) {
        Date date = new Date();
//        // 将结束巡护的位置存入位置信息

        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setPatrolId(request.getId());
        locationRequest.setCreateTime(date);
        locationRequest.setLon(request.getLon());
        locationRequest.setLat(request.getLat());
        locationRequest.setIsEvent(0);

        this.location(locationRequest);

        //添加开始经纬度到位置信息表

//        LocationInfoEntity locationInfoEntity = new LocationInfoEntity();
//        locationInfoEntity.setCreateTime(new Date());
//        locationInfoEntity.setLon(request.getLon());
//        locationInfoEntity.setLat(request.getLat());
//        locationInfoEntity.setIsEvent(0);
//        locationInfoEntity.setPatrolId(request.getId());
//        locationInfoService.save(locationInfoEntity);

        String username = UserUtil.getCurrentUser();
        // 获取巡护事件
        PatrolEntity patrolEntity = this.getById(request.getId());
        if (patrolEntity == null) {
            return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "巡护不存在!");
        }
        if (!username.equals(patrolEntity.getCreateBy())) {
            return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "不可结束非自己创建的巡护!");
        }
        if (!StateEnum.PATROL_STATE.UNDERWAY.getState().equals(patrolEntity.getState())) {
            return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "只能结束巡护中的巡护");
        }


        BeanUtils.copyProperties(request, patrolEntity);
        patrolEntity.setEndLat(request.getLat());
        patrolEntity.setEndLon(request.getLon());

        patrolEntity.setEndTime(date);
        patrolEntity.setModifyTime(date);
        patrolEntity.setState(StateEnum.PATROL_STATE.END.getState());
//        patrolEntity.setHeight(request.height);

        // 计算毫秒值
        long betweenDay = DateUtil.between(patrolEntity.getStartTime(), date, DateUnit.MS);
        patrolEntity.setWhenTime(betweenDay);

        // 覆盖面积=巡护公里数*0.2 每次计算巡护公里数时更新

//        BigDecimal mul = NumberUtil.mul(patrolEntity.getRoute(), "0.2");
//
//        patrolEntity.setCoverArea(NumberUtil.roundStr(mul.doubleValue(), 2));

        // 计算距离
        Double route = countLocation(request.getId());
        if (route != null) {
            //计算巡护面积，公式：巡护里程（千米）* 0.2，保留4位小数
            Float f = 1000f;
            String routeStr = NumberUtil.roundStr(route, 2);
            String coverArea = NumberUtil.roundStr(NumberUtil.mul(NumberUtil.div(route, f), 0.2).doubleValue(), 4);
            patrolEntity.setRoute(routeStr);
            patrolEntity.setCoverArea(coverArea);
        }

        boolean flag = this.updateById(patrolEntity);


        if (flag) {
            return Result.ok("ok");
        }
        return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "操作失败请稍后再试");
    }

    /**
     * 计算距离
     *
     * @param patrolId
     * @return
     */
    public Double countLocation(Long patrolId) {
        try {
            long time = new Date().getTime();
            List<LocationInfoEntity> list = locationInfoService.list(new LambdaQueryWrapper<LocationInfoEntity>().eq(LocationInfoEntity::getPatrolId, patrolId).orderByAsc(LocationInfoEntity::getCreateTime));
            // 根据经纬度去重
//            List<LocationInfoEntity> collect = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getLon() + "," + o.getLat()))), ArrayList::new));
            Double sum = 0.0;
            for (int i = 0; i < list.size() - 1; i++) {
                Double distance = GeoUtils.distance(Double.parseDouble(list.get(i).getLon()), Double.parseDouble(list.get(i).getLat()), Double.parseDouble(list.get(i + 1).getLon()), Double.parseDouble(list.get(i + 1).getLat()));
                Double d = Double.parseDouble(NumberUtil.roundStr(distance, 4));
                sum += d;
            }
//            Float f = 1000f;
//            Double route = NumberUtil.roundStr(sum, 4);
//            LambdaUpdateWrapper<PatrolEntity> wrapper = new LambdaUpdateWrapper<>();
//            wrapper.eq(PatrolEntity::getId, patrolId);
//            wrapper.set(PatrolEntity::getRoute, route);
//            //计算巡护面积，公式：巡护里程（千米）* 0.2，保留4位小数
//            String coverArea = NumberUtil.roundStr(NumberUtil.mul(NumberUtil.div(sum, f), 0.2).doubleValue(), 4);
//            wrapper.set(PatrolEntity::getCoverArea, coverArea);
//            patrolMapper.update(null, wrapper);
            log.info("计算完成,距离(米):{},巡护id:{},耗时:{},线程:{}", sum, patrolId, new Date().getTime() - time, Thread.currentThread().getName());
            return sum;
        } catch (Exception e) {
            log.error("计算距离异常{}", e);
            throw new ServerException("结束巡护失败，计算巡护距离失败");
        }
    }

    @Override
    public Result<?> check() {
        String username = UserUtil.getCurrentUser();
        PatrolEntity patrolByName = this.getPatrolByName(username);

        if (patrolByName == null) {
            return Result.ok(null);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("patrolId", patrolByName.getId());
        jsonObject.put("type", patrolByName.getType());
        return Result.ok(jsonObject);
    }

    @Override
    public PatrolEntity getPatrolByName(String name) {
        return this.getOne(new LambdaQueryWrapper<PatrolEntity>().eq(PatrolEntity::getState, StateEnum.PATROL_STATE.UNDERWAY.getState()).eq(PatrolEntity::getCreateBy, name), false);
    }


    /**
     * 对订单进行补位
     *
     * @param ordString
     * @param len
     * @param alexin
     * @return
     */
    public static String padRight(String ordString, int len, String alexin) {
        StringBuffer s = new StringBuffer("");
        //需求长度-实际长度得到的差，如果>0则需要补位，差值就是需要的补位的长度
        for (int i = 0; i < len - ordString.length(); i++) {
            s.append(alexin);
        }
        return s + ordString;
    }

    @Override
    public String createOrderNum(String type, String format) {
        //设置key日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat numberFormat = new SimpleDateFormat(format);
        String keyDate = dateFormat.format(System.currentTimeMillis());
        String numberDate = numberFormat.format(System.currentTimeMillis());
        String key = "number:" + type + keyDate;

        String padString = "";

        ValueOperations<String, String> forValue = redisTemplate.opsForValue();
        if (redisTemplate.hasKey(key)) {
            Long increment = forValue.increment(key);
            //得到补位过后的字符串
            padString = padRight(String.valueOf(increment), 4, "0");
            return type + numberDate + padString;
        } else {
            RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
            //设置初值
            redisAtomicLong.set(0);
//            //设置最多24小时后过期，保证最多只有一天的记录在redis中
//            redisAtomicLong.expire(24, TimeUnit.HOURS);
            //设置创建订单的一天结束时间过期
            redisAtomicLong.expireAt(DateUtil.endOfDay(new Date()));
            Long increment = forValue.increment(key);
            //得到补位过后的字符串
            padString = padRight(String.valueOf(increment), 4, "0");

            //将字符串拼接成需要的格式，并返回
            return type + numberDate + padString;
        }
    }

    @Override
    public PatrolSumDTO countData(PatrolQueryPageRequest request) {
        try {
            // 获取当年所有的巡护事件
//            Date date = new Date();
//            DateTime endOfYear = DateUtil.endOfYear(date);
//            DateTime beginOfDay = DateUtil.beginOfYear(date);
//            List<PatrolEntity> patrolEntities = this.list(new LambdaQueryWrapper<PatrolEntity>().ge(PatrolEntity::getStartTime, beginOfDay).le(PatrolEntity::getEndTime, endOfYear));
            if (!StringUtils.isEmpty(request.getType())) {
                request.setTypes(Arrays.asList(request.getType().split(",")));
            }
            List<PatrolEntity> patrolEntities = this.baseMapper.getByYear(request);
            // 根据类型分组
            Map<String, List<PatrolEntity>> typeMap = patrolEntities.stream().collect(Collectors.groupingBy(PatrolEntity::getType));
            PatrolSumDTO patrolSumDTO = new PatrolSumDTO();

            if (CollectionUtils.isEmpty(typeMap)) {
                patrolSumDTO.setYangXianCount(0);
                patrolSumDTO.setYangXianEventCount(0L);
//                patrolSumDTO.setYangXianTimeCount(null);
                patrolSumDTO.setYangXianRouteCount("0");
                patrolSumDTO.setRiChangCount(0);
                patrolSumDTO.setRiChangEventCount(0L);
//                patrolSumDTO.setRiChangTimeCount(null);
                patrolSumDTO.setRiChangRouteCount("0");
            }
            // 样线巡护
            List<PatrolEntity> yangXian = typeMap.get(StateEnum.PATROL_TYPE.TRANSECT.getType());
            if (CollectionUtils.isEmpty(yangXian)) {
                patrolSumDTO.setYangXianCount(0);
                patrolSumDTO.setYangXianEventCount(0L);
                patrolSumDTO.setYangXianRouteCount("0");
            } else {
                patrolSumDTO.setYangXianCount(yangXian.size());
                // 获取所有样线id
                List<Long> yangXianIds = yangXian.stream().map(PatrolEntity::getId).collect(Collectors.toList());
                // 查询巡护下的所有事件数量
                long count = reportService.count(new LambdaQueryWrapper<ReportEntity>().in(ReportEntity::getPatrolId, yangXianIds));

                patrolSumDTO.setYangXianEventCount(count);

//                // 计算巡护总时常(毫秒值)
//                long sum = yangXian.stream().filter(patrolEntity -> patrolEntity.getWhenTime() != null).mapToLong(PatrolEntity::getWhenTime).sum();
//                if (sum == 0) {
//                    patrolSumDTO.setYangXianTimeCount(null);
//                } else {
////                    patrolSumDTO.setYangXianTimeCount(DateUtil.formatBetween(sum));
//                    patrolSumDTO.setYangXianTimeCount(dateUtils.msToHor(sum));
//                }
                // 计算巡护总里程
                double yangXianSum = yangXian.stream().filter(patrolEntity -> patrolEntity.getRouteKm() != null).mapToDouble(item -> Double.parseDouble(item.getRouteKm())).sum();
                patrolSumDTO.setYangXianRouteCount(yangXianSum == 0 ? "0" : NumberUtil.roundStr(yangXianSum, 2));

            }

            // 日常巡护
            List<PatrolEntity> riChang = typeMap.get(StateEnum.PATROL_TYPE.DAILY.getType());
            if (CollectionUtils.isEmpty(riChang)) {
                patrolSumDTO.setRiChangCount(0);
                patrolSumDTO.setRiChangEventCount(0L);
//                patrolSumDTO.setRiChangTimeCount(null);
                patrolSumDTO.setRiChangRouteCount("0");
            } else {
                patrolSumDTO.setRiChangCount(riChang.size());
                // 获取所有样线id
                List<Long> riChangIds = riChang.stream().map(PatrolEntity::getId).collect(Collectors.toList());
                // 查询巡护下的所有事件数量
                long count = reportService.count(new LambdaQueryWrapper<ReportEntity>().in(ReportEntity::getPatrolId, riChangIds));

                patrolSumDTO.setRiChangEventCount(count);

//                // 计算巡护总时常(毫秒值)
//                long sum = riChang.stream().filter(patrolEntity -> patrolEntity.getWhenTime() != null).mapToLong(PatrolEntity::getWhenTime).sum();
//
//                if (sum == 0) {
//                    patrolSumDTO.setRiChangTimeCount(null);
//                } else {
////                    patrolSumDTO.setRiChangTimeCount(DateUtil.formatBetween(sum));
//                    patrolSumDTO.setRiChangTimeCount(dateUtils.msToHor(sum));
//                }
                // 计算巡护总里程
                double riChangSum = riChang.stream().filter(patrolEntity -> patrolEntity.getRouteKm() != null).mapToDouble(item -> Double.parseDouble(item.getRouteKm())).sum();
                patrolSumDTO.setRiChangRouteCount(NumberUtil.roundStr(riChangSum, 2));

            }
            //patrolSumDTO.setType(StringUtils.isEmpty(request.getType()) ? "All" : StateEnum.PATROL_TYPE.getEnum(request.getType()).getType());

            return patrolSumDTO;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    @Override
    public List<Long> getIdsByType(String type) {
        List<Long> ids;
        List<PatrolEntity> list = this.list(new LambdaQueryWrapper<PatrolEntity>()
                .eq(PatrolEntity::getType, type));
        ids = list.stream().map(PatrolEntity::getId).distinct().collect(Collectors.toList());
        return ids;
    }

    @Override
    public PatrolCountDTO countPatrol(String type) {
        //获取当前对象
        String name =
                UserUtil.getCurrentUser();
        PatrolCountDTO patrolCountDTO = new PatrolCountDTO();
        DateTime startTime = DateUtil.beginOfYear(new Date());
        DateTime endTime = DateUtil.endOfYear(new Date());
        Long endSum = this.baseMapper.countPatrol(name, type, startTime, endTime);
        long report = reportService.countReport(name, type, startTime, endTime);  //上报事件

        patrolCountDTO.setEndSum(endSum);//设置年度巡护数量
        patrolCountDTO.setReportSum(report);


        return patrolCountDTO;
    }


    @Override
//    @Transactional
    public Page<PatrolListDTO> PatrolList(PatrolListRequest request) {
        try {
            String name = UserUtil.getCurrentUser();
            Page<PatrolListDTO> page = new Page<>(request.getPageNum(), request.getPageSize());
            Page<PatrolListDTO> pageData = this.baseMapper.patrolList(page, name, request.getType());
            //设置时间和 图片
            pageData.getRecords().forEach(
                    //设置时间  图片和 资源查询
                    item -> {
                        //设置巡护状态
                        item.setStateDes(StateEnum.PATROL_STATE.getEnum(item.getState()).getDesc());
                        //设置类型描述
                        item.setTypeDes(StateEnum.PATROL_TYPE.getEnum(item.getType()).getDesc());
                        //设置时间段
                        if (item.getEndTime() == null) {
                            String startDate = DateUtil.format(item.getStartTime(), "yyyy.MM.dd HH:mm");
                            item.setPatrolDate(startDate);
                        } else {
                            item.setPatrolDate(dateUtils.sub(item.getStartTime(), item.getEndTime(), "~"));
                        }
                        //拼接名字
                        if (StringUtils.isEmpty(item.getOthersPeople())) {
                            item.setJoin(item.getPeople());
                        } else if (StringUtils.isEmpty(item.getPeople())) {
                            item.setJoin(item.getOthersPeople());
                        } else if ((!StringUtils.isEmpty(item.getOthersPeople())) &&
                                (!StringUtils.isEmpty(item.getPeople()))) {
                            item.setJoin(item.getPeople() + "；" + item.getOthersPeople());
                        }
                        List<UrlDTO> picture = resourceService.getUrlByPatrolId(
                                StateEnum.RESOURCE_TYPE.PICTURE.getType(), item.getId());
                        List<UrlDTO> video = resourceService.getUrlByPatrolId(
                                StateEnum.RESOURCE_TYPE.VIDEO.getType(), item.getId());
                        if (!CollectionUtils.isEmpty(picture)) {
                            item.setPicture(picture);
                        }
                        if (!CollectionUtils.isEmpty(video)) {
                            item.setVideo(video);
                        }
                    }

            );
            return pageData;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    @Override
    public Result<MyPatrolDTO> myPatrol() {
        String name =
                UserUtil.getCurrentUser();
        MyPatrolDTO myPatrolDTO = this.baseMapper.myPatrolSum(name);
        return Result.ok(myPatrolDTO);

    }

    @Override
    public Long getCountPatrol(String type, PageReportRequest request) {
        return this.baseMapper.getCountPatrol(type, request);
    }

    @Override
    public UpdateInfoDTO updateInfo(Long patrolId) {
        PatrolEntity patrolEntity = this.getById(patrolId);
        if (patrolEntity == null) {
            return new UpdateInfoDTO();
        }
        UpdateInfoDTO updateInfoDTO = new UpdateInfoDTO();
        BeanUtils.copyProperties(patrolEntity, updateInfoDTO);
        updateInfoDTO.setPatrolId(patrolId);
        if (!StringUtils.isEmpty(patrolEntity.getPeople())) {
            updateInfoDTO.setPeopleNames(Arrays.asList(patrolEntity.getPeople().split("；")));
        }
        if (!StringUtils.isEmpty(patrolEntity.getOthersPeople())) {
            updateInfoDTO.setPeopleNames(Arrays.asList(patrolEntity.getOthersPeople().split("；")));
        }
        return updateInfoDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> BatchLocation(BatchLocationRequest request) {
        try {
            List<LocationInfoEntity> locationInfoEntities = BeanUtil.copyToList(request.getLocations(), LocationInfoEntity.class);
            locationInfoService.saveBatch(locationInfoEntities);
            Long patrolId = request.getLocations().get(0).getPatrolId();
            // 有可能是删除以后提交的事件，至于为什么删除之后还需要提交位置信息，我也很想知道
            PatrolEntity patrolEntity = this.baseMapper.getById(patrolId);
//            PatrolEntity patrolEntity = this.getById(patrolId);
            // 离线上报时如果是已结束的巡护进行距离计算
            if (StateEnum.PATROL_STATE.END.getState().equals(patrolEntity.getState())) {
                asyncPatrolService.asyncCountLocation(patrolId);
            }
            return Result.ok();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("批量上传位置信息失败:{}", e);
            return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "批量上传位置信息失败");
        }

    }

    @Override
    public HeightDTO getHeight(Long id) {
        //根据巡护id查询，
        HeightDTO heightDTO = new HeightDTO();
        PatrolEntity byId = this.getById(id);
        //只对巡护中的巡护进行计算
        List<String> heights;
        List<Double> heightD = new ArrayList<>();
        if (byId.getState().equals(StateEnum.PATROL_STATE.UNDERWAY.getState())) {
            //获取名下所有事件的海拔
            List<ReportEntity> list = reportService.list(new LambdaQueryWrapper<ReportEntity>().eq(ReportEntity::getPatrolId, id));
            heights = list.stream().map(ReportEntity::getElevation).distinct().collect(Collectors.toList());
            for (String height : heights) {
                if (!StringUtils.isEmpty(height)) {
                    if (NumberUtil.isNumber(height)) {
                        BigDecimal round = NumberUtil.round(height, 3);
                        heightD.add(new Double(String.valueOf(round)));
                    }
                }

                if (!CollectionUtils.isEmpty(heightD) && heightD.size() > 1) {
                    Double min = Collections.min(heightD);
                    Double max = Collections.max(heightD);
                    double sub = NumberUtil.sub(max, min);

                    heightDTO.setHeight(sub + "");
                } else if (CollectionUtils.isEmpty(heightD)) {
                    heightDTO.setHeight(0 + "");
                } else if (heightD.size() == 1) {
                    heightDTO.setHeight(heightD.get(0) + "");
                }
            }

        }
        return heightDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void location(LocationRequest request) {
//        PatrolEntity patrolEntity = this.getById(request.getPatrolId());
//        if (patrolEntity == null) {
//            throw new ServerException("巡护不存在");
//        }
//        if (!StateEnum.PATROL_STATE.UNDERWAY.getState().equals(patrolEntity.getState())){
//            throw new ServerException("只有巡护中才能进行位置上传");
//        }
        // 获取上一次数据
//        LocationInfoEntity locationInfoEntity = locationInfoMapper.newLocationByPatrol(request.getPatrolId());
//        // 计算两个点位之间的距离
//        Double distance = GeoUtils.distance(Double.valueOf(locationInfoEntity.getLon()),
//                Double.valueOf(locationInfoEntity.getLat()),
//                Double.valueOf(request.getLon()),
//                Double.valueOf(request.getLat()));

        //位置信息写入数据库
        LocationInfoEntity locationInfoNew = new LocationInfoEntity();
        BeanUtils.copyProperties(request, locationInfoNew);
//        locationInfoNew.setIsEvent(0);
//        if (locationInfoNew.getCreateTime() == null) {
//            locationInfoNew.setCreateTime(new Date());
//        }
        locationInfoService.save(locationInfoNew);


        // 距离信息写入巡护表
        /*
         * 距离单位米，客户端每30秒提交一次位置信息
         * 允许有1米的误差，每次计算超过5米以后才纳入总路程进行计算
         */
//        if (distance > 0.00){
//            this.baseMapper.setRoute(distance, request.getPatrolId());
//        }
        // 异步计算距离
//        asyncPatrolService.asyncCountLocation(request.getPatrolId());

    }

    @Override
    public Page<PatrolPageDTO> page(PatrolQueryPageRequest request) {
        try {
            Page<PatrolPageDTO> page = new Page<>(request.getPageNum(), request.getPageSize());
            // 解析机构id
            if (!StringUtils.isEmpty(request.getTotalOrgId())) {
                request.setOrgIds(Arrays.asList(request.getTotalOrgId().split(",")));
            }
            // 解析类型
            if (!StringUtils.isEmpty(request.getType())) {
                request.setTypes(Arrays.asList(request.getType().split(",")));
            }
            // 解析状态
            if (!StringUtils.isEmpty(request.getState())) {
                request.setStates(Arrays.asList(request.getState().split(",")));
            }
            page = this.baseMapper.queryPage(page, request);
//        String format = "yyyy-MM-dd HH:mm";
            page.getRecords().forEach(item -> {
//            item.setPatrolDate(DateUtil.format(item.getStartTime(), format));
//            if (item.getEndTime() != null){
//                item.setPatrolDate(item.getPatrolDate() + "到" + DateUtil.format(item.getEndTime(), format));
//            }
                // 计算巡护时常
                if (!StringUtils.isEmpty(item.getWhenTime())) {
//                item.setWhenTime(DateUtil.formatBetween(Long.valueOf(item.getWhenTime())));
                    item.setWhenTime(dateUtils.msToHour(item.getWhenTime()));
                }
                //类型转换
                item.setType(StateEnum.PATROL_TYPE.getEnum(item.getType()).getDesc());
                //状态转换
                item.setState(StateEnum.PATROL_STATE.getEnum(item.getState()).getDesc());

                if (!StringUtils.isEmpty(item.getPeople())) {
                    item.setPeopleNames(Arrays.asList(item.getPeople().split("；")));
                }

                //拼接其他人
                if (StringUtils.isEmpty(item.getOthersPeople())) {
                    item.setPeople(item.getPeople());
                } else if (StringUtils.isEmpty(item.getPeople())) {
                    item.setPeople(item.getOthersPeople());
                } else if ((!StringUtils.isEmpty(item.getOthersPeople())) &&
                        (!StringUtils.isEmpty(item.getPeople()))) {
                    item.setPeople(item.getPeople() + "；" + item.getOthersPeople());
                }
            });
            return page;
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServerException("获取巡护列表失败");
        }

    }

    @Override
    public UserOrgVo getOrgByName(String name) {
        //查询用户
        User dbUser = userService.getById(name);
        if (ObjectUtils.isEmpty(dbUser)) return null;
        //查询机构
        Org org = orgService.getById(dbUser.getOrgId());

        UserOrgVo userOrgVo = new UserOrgVo();
        userOrgVo.setUsername(name);
        if (!ObjectUtils.isEmpty(org)) {
            if (!StringUtils.isEmpty(org.getType())) {
                if ("0" == org.getType()) {
                    //用户所属最高级
                    userOrgVo.setAbbr(org.getAbbr());
                } else if ("1" == org.getType()) {
                    //自己所属总站
                    userOrgVo.setAbbr(org.getAbbr());
                    userOrgVo.setTotleOrg(org.getName());
                    userOrgVo.setTotleOrgId(org.getId());
                } else {
                    //用户所属为分站
                    Org totleOrg = orgService.getById(org.getParentId());
                    userOrgVo.setAbbr(totleOrg.getAbbr());
                    userOrgVo.setTotleOrg(totleOrg.getName());
                    userOrgVo.setTotleOrgId(totleOrg.getId());
                    userOrgVo.setBranchOrg(org.getName());
                    userOrgVo.setBranchOrgId(org.getId());
                }
            }
        }
        return userOrgVo;
    }

    @Override
    public Result<?> remove(Long id) {
        // 删除巡护
        Boolean flag = this.removeById(id);
        // 删除巡护下的事件，如果存在
        List<ReportEntity> list = reportService.list(new LambdaQueryWrapper<ReportEntity>().eq(ReportEntity::getPatrolId, id));
        if (!CollectionUtils.isEmpty(list)) {
            List<Long> ids = list.stream().map(ReportEntity::getId).collect(Collectors.toList());
            flag = reportService.removeByIds(ids);
        }
        // 删除巡护下的资源，如果存在
        List<ReportResourceEntity> listResource = reportResourceService.list(
                new LambdaQueryWrapper<ReportResourceEntity>().eq(ReportResourceEntity::getPatrolId, id));
        if (!CollectionUtils.isEmpty(listResource)) {
            List<Long> ids = listResource.stream().map(ReportResourceEntity::getId).collect(Collectors.toList());
            flag = reportResourceService.removeByIds(ids);
        }
        // 删除巡护位置信息
        locationInfoService.remove(new LambdaQueryWrapper<LocationInfoEntity>().eq(LocationInfoEntity::getPatrolId, id));


        if (flag) {
            return Result.ok("ok");
        }
        return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "删除失败请稍后再试");
    }

    @Override
    public Result<?> update(UpdatePatrolRequest request) {
        String username = UserUtil.getCurrentUser();
        PatrolEntity patrolEntity = this.getById(request.getId());
        if (patrolEntity == null) {
            return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "巡护不存在");
        }
        BeanUtils.copyProperties(request, patrolEntity);
//        // 拼接巡护人员信息
//        if (!CollectionUtils.isEmpty(request.getPatrolNames())) {
//            patrolEntity.setPeople(request.getPatrolNames().stream().collect(Collectors.joining("、")));
//        } else {
//            patrolEntity.setPeople("");
//        }
//        // 拼接其他人员信息
//        if (!CollectionUtils.isEmpty(request.getOthersPatrolNames())) {
//            patrolEntity.setOthersPeople(request.getOthersPatrolNames().stream().collect(Collectors.joining("、")));
//        } else {
//            patrolEntity.setOthersPeople("");
//        }
//        // 拼接单位信息
//        if (!CollectionUtils.isEmpty(request.getUnits())) {
//            patrolEntity.setUnit(request.getUnits().stream().collect(Collectors.joining("、")));
//        }
        patrolEntity.setModifyBy(username);
        patrolEntity.setModifyTime(new Date());
        boolean flag = this.updateById(patrolEntity);
        if (flag) {
            return Result.ok("ok");
        }
        return Result.write(StateEnum.RESULT_CODE.ERROR.getCode(), "修改失败请稍后再试");
    }


    @Override
    public DetailListDTO getPatrolById(Long id) {
        return this.baseMapper.getPatrolById(id);
    }

    @Override
    public void export(HttpServletResponse response, PatrolQueryPageRequest request) {
//        PatrolQueryPageRequest request = new PatrolQueryPageRequest();
        request.setPageSize(-1);
        Page<PatrolPageDTO> page = this.page(request);
        List<ExPatrolDTO> exPatrolDTOS = BeanUtil.copyToList(page.getRecords(), ExPatrolDTO.class);
        try {
            EasypoiExcelUtils.exportExcel(exPatrolDTOS, null, "sheet1", ExPatrolDTO.class, "巡护信息表.xls", response);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("导出巡护信息失败");
        }
    }

    /**
     * 检测是否重复提交,检测5秒内
     *
     * @param key 防重复提交key
     * @return 有提交true, 没提交false
     */
    public Boolean submit(String key) {
        String submitKey = redisUtils.get(key);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(submitKey)) {
            return true;
        }
        // 未重复提交保存重复提交key
        redisUtils.set(key, "0", 5);
        return false;
    }

}
